#include "NRJB/NRJB103Client.h"
#include "ui_PanelNRJB_TCPClient.h"

NRJB103Client::NRJB103Client(QWidget *parent) :
    QWidget(parent),ui(new Ui::PanelNRJB_TCPClient)    //南瑞继保 103 默认tcp端口哦6000
{
    ui->setupUi(this);

    ui->lineEditTcpServerAddr->setText("192.168.0.220"); //192.168.0.220
    ui->lineEditTcpServerPort->setText("6000");

    connect(ui->pushButtonSend, &QPushButton::clicked, this, &NRJB103Client::slot_send);
    connect(ui->pushButtonConnect, &QPushButton::clicked, this, &NRJB103Client::slot_pushButtonConnect_clicked);

    m_connection = new NRJBConnection();
    m_connection->setParent(0);

    ui->pushButtonSend->setEnabled(false);

    ui->pushButtonConnect->setText("连接");

    ui->comboBoxLocalHostAddr->addItems(m_connection->getLocalHostIPList());

    ui->radioButtonHeart->setEnabled(false);
    ui->pushButtonSendCombox->setEnabled(false);

    m_timerGetParseResult.setSingleShot(true);

    // 连接状态刷新界面控件状态
    connect(m_connection, &NRJBConnection::sig_disconnect, this, &NRJB103Client::slot_updateUiAsDisconnect);
    connect(m_connection, &NRJBConnection::sig_connected, this, &NRJB103Client::slot_updateUiAsConnected);
    connect(m_connection, &NRJBConnection::sig_connectTimeOut, this, &NRJB103Client::slot_ConnectError);
    connect(m_connection, &NRJBConnection::sig_sendMsg, this, &NRJB103Client::slot_updateUiAsSend);

    // 将报文解析结果传给 定值显示界面
    // connect(&m_NRJBParser, SIGNAL(sig_parseFinished(QStringList,int)), &m_panelBill, SLOT(onRecv(QStringList, int)));

    // 接收 tcp 消息
    connect(m_connection, &NRJBConnection::sig_readyRead, this, &NRJB103Client::slot_recv);

    // 标题解析结束束是解析定值模板的前题
    connect(&m_NRJBParser, &NRJB103_Parser::sig_getTitlesFinished, this, &NRJB103Client::slot_setCanReadBillInfo);

    // 显示定值信息, 正式解析 存在 m_recvList 中的报文为可读
    connect(ui->pushButtonShowBill, &QPushButton::clicked, this, &NRJB103Client::slot_pushButtonShowBill_clicked);
    connect(ui->pushButtonReadAll, &QPushButton::clicked, this, &NRJB103Client::slot_pushButtonReadAll_clicked);
    //connect(this, &PanelNRJB_TCPClient::sig_requestDeviceData, this, &PanelNRJB_TCPClient::slot_pushButtonReadAll_clicked);

    connect(&m_timerReadDeviceRequest, &QTimer::timeout, this, &NRJB103Client::slot_responseForUserApi);

    connect(&m_timerGetParseResult, &QTimer::timeout, this, &NRJB103Client::slot_getBillInfo); 

    m_parserThread = new QThread;
    m_NRJBParser.moveToThread(m_parserThread);
    connect(this, &NRJB103Client::sig_parserRecv, &m_NRJBParser, &NRJB103_Parser::slot_threadWork);
    m_parserThread->start();
}

NRJB103Client::~NRJB103Client()
{
    delete ui;
    delete m_connection;
    delete m_parserThread;
}

void NRJB103Client::readDeviceAll()
{
    //    emit sig_requestDeviceData();       // 用户请求发出

    // 当没有连接成功的时候需要定时不断的发出直到连接成功
    m_timerReadDeviceRequest.start(200);

    m_timerGetParseResult.start(TIME_GETDATA);
}

void NRJB103Client::showTable()
{
    if (m_panelBill.checkTableDataSets()) {
        m_panelBill.show();
    }
}

void NRJB103Client::getAllBillInfo(QMap<QString, BillTableStruct> &tablesStaructBuffer)
{

    qDebug() << "**** 南瑞继保开始获取结果**** ";
    //肯能没有读完就取出来了定值信息，需要确认读取完毕信号已经收到
//    tablesStaructBuffer = m_NRJBParser.getStructBillInfo();

    tablesStaructBuffer = m_tablesInfo;
    foreach (BillTableStruct it, tablesStaructBuffer) {
        qDebug() << "********* table 信息如下 ************ ";
        qDebug() << "组号 = " << it.groupNo << "组名 = " << it.groupName << it.billRealValueList;
    }

    qDebug() << "client 层结果" << tablesStaructBuffer.count();
}

void NRJB103Client::disConnectDevice()
{
    m_connection->disconnectFromDevice();
}

void NRJB103Client::setBillGroup(QStringList &)
{

}

QStringList NRJB103Client::getErrorLog()
{
    return m_errorList;
}

void NRJB103Client::slot_send()
{
    QString m_sendMsg = ui->lineEditTcpMsg->text();
    emit sig_sendClicked();
    m_sendMsg.remove(' ');
    m_connection->sendTcpMsg(m_sendMsg);
}

void NRJB103Client::slot_recv()
{
     ui->textBrowserRecv->append("[接收]: " +  m_connection->getRecvTcpMsg().toHex());

     //解析接受到的报文,将接受报文传给解析逻辑层
     QByteArray recvMsgBytes =  m_connection->getRecvTcpMsg();
    // qDebug() << "收到的原始byte 数据 " << recvMsgBytes;

     m_recvList.append(recvMsgBytes);   // 具体解析这一步可以推迟到用户点击展示的时候，先保存全部接收到的数据

//     m_NRJBParser.parseNRJBPackets(recvMsgBytes);

     emit sig_parserRecv(recvMsgBytes);
     qDebug() << "NRJB103Client 线程 ID = " <<QThread::currentThreadId();
}

void NRJB103Client::slot_updateUiAsDisconnect()
{
    ui->lineEditTcpServerAddr->setEnabled(true);
    ui->lineEditTcpServerPort->setEnabled(true);
    ui->comboBoxLocalHostAddr->setEnabled(true);
    ui->pushButtonConnect->setEnabled(true);

    ui->radioButtonHeart->setEnabled(false);
    ui->pushButtonSend->setEnabled(false);
    ui->pushButtonConnect->setText("连接");
    ui->pushButtonSendCombox->setEnabled(false);
    ui->pushButtonSend->setEnabled(false);
    ui->radioButtonHeart->setChecked(false);

    isCanComminucate = false;
}

void NRJB103Client::slot_updateUiAsConnected()
{
    ui->pushButtonSend->setEnabled(true);
    ui->pushButtonConnect->setText("断开");
    ui->lineEditTcpServerPort->setEnabled(false);
    ui->lineEditTcpServerAddr->setEnabled(false);
    ui->radioButtonHeart->setEnabled(true);
    ui->comboBoxLocalHostAddr->setEnabled(false);
    ui->pushButtonSendCombox->setEnabled(true);

    isCanComminucate = true;
}

void NRJB103Client::slot_updateUiAsSend(QString sendMsg)
{
    ui->textBrowserRecv->append(sendMsg);
}

void NRJB103Client::connectDevice(QString devAddr, QString devPort, QString localAddr, QString localPort)
{
    if ( Utils::checkIpFormat(devAddr) == false && Utils::checkIpFormat(localAddr) == false )
    {
        qDebug() << m_errorList << "设备地址格式错误！";
    }

    localPort = nullptr; // 南瑞继保的客户端是tcp 客户端，不需要这个
//    m_client->disconnectFromDevice();

   // 从界面获取通讯参数，传给tcp 服务层，以备报文构造使用
    m_connection->setIPPortAndConnect( devAddr, devPort, localAddr);
}

void NRJB103Client::slot_pushButtonConnect_clicked()
{
    if (ui->pushButtonConnect->text() == "连接")
    {
        // 从界面获取通讯参数，传给tcp 服务层，以备报文构造使用
        m_connection->setIPPortAndConnect( ui->lineEditTcpServerAddr->text(), ui->comboBoxLocalHostAddr->currentText(), ui->lineEditTcpServerPort->text());
    }

    // 断开连接
    else
    {
        m_connection->disconnectFromDevice();
    }
}

void NRJB103Client::on_pushButtonClear_clicked()
{
    ui->textBrowserRecv->clear();
    m_NRJBParser.clearParseResultBuffer();
}

void NRJB103Client::on_pushButtonSendCombox_clicked()
{
    // 发送心跳
    int index = ui->comboBox->currentIndex();
    if (index == 0)
    {
        //QByteArray  heartCmd = "90eb1400000090eb0000dc000000010000002b00500000000000ffff";
        m_connection->startHeartTimer();
    }
    else if (index == 1)
    {
        QByteArray readTitleCmd = "";
        readTitleCmd = m_nrjbPacketConstructer.constructReadAllTitles(ui->lineEditTcpServerAddr->text(), ui->comboBoxLocalHostAddr->currentText());
        m_connection->sendTcpMsg(readTitleCmd);
    }
}


void NRJB103Client::on_radioButtonHeart_clicked(bool checked)
{
    if(checked == true)
    {
        m_connection->startHeartTimer();
    }
    else
    {
        m_connection->stopHeartTimer();
    }
}

void NRJB103Client::slot_pushButtonShowBill_clicked()
{
    //获取解析接收到的全部报文
//    foreach (QByteArray packet, m_recvList)
//    {
//        m_NRJBParser.parseNRJBPackets(packet);
//    }

    QList<QStringList>  billTableInfo =  m_NRJBParser.getBillTablesInfo();

    // 表格结构信息传个界面
    m_panelBill.showBillTables(billTableInfo);

}

void NRJB103Client::on_pushButtonReadGroup_clicked()
{
    QString  groupNo  = ui->lineEditGroupNo->text();    // 10进制字符

    QString kod;
    // 描述
    if (ui->comboBoxRequireKOD->currentText().contains("描述"))
    {
        kod = KOD_DESCRIPTER;
    }
    else if (ui->comboBoxRequireKOD->currentText().contains("实际值"))
    {
        kod = KOD_REAL_VALUE;
    }
    else if (ui->comboBoxRequireKOD->currentText().contains("默认值"))
    {
        kod = KOD_DEFAULT_VALU;
    }
    // 目标设备地址
    ushort srcAddr = Utils::uintStrToHexStr(ui->comboBoxLocalHostAddr->currentText().split('.')[3],4).toUInt(nullptr,16);
    ushort destAddr = (Utils::uintStrToHexStr(ui->lineEditTcpServerAddr->text().split('.')[3],4)).toUInt(nullptr,16);
    qDebug() << "src addr " << Utils::uintStrToHexStr(ui->comboBoxLocalHostAddr->currentText().split('.')[3],4) << srcAddr << "dest addr " << destAddr;

    // 读取单个
    QByteArray cmdReadGroup =  m_nrjbPacketConstructer.constructReadGroupInfo(srcAddr, destAddr, groupNo, kod);

    ui->lineEditTcpMsg->setText(cmdReadGroup);
}


void NRJB103Client::readAllGroupsInfo()
{
    ushort destAddr = Utils::uintStrToHexStr(ui->lineEditTcpServerAddr->text().split('.')[3],4).toUInt(nullptr,16);
    ushort srcAddr = Utils::uintStrToHexStr(ui->comboBoxLocalHostAddr->currentText().split('.')[3],4).toUInt(nullptr,16);

    // 请求全部组的具体信息
    QByteArrayList cmdList;
    QByteArray tmpCmd;

    QStringList kodLiST = {KOD_DESCRIPTER, KOD_REAL_VALUE, KOD_UNIT, KOD_DIMENSION};
    foreach (QString it, m_NRJBParser.getAboutBillGroupInfo().keys())
    {
        qDebug() << "***************************第 " << it << " 组***************************";
        foreach (QString it_kod, kodLiST)
        {
            qDebug() << "***************************第 " << it << " 组***************************";
            tmpCmd = m_nrjbPacketConstructer.constructReadGroupInfo(srcAddr,destAddr, it, it_kod);
            cmdList.append(tmpCmd);
        }
    }
    m_connection->sendTcpMsg(cmdList);
}

void NRJB103Client::readAllTitlesInfo()
{
    QByteArray readTitleCmd = "";
    readTitleCmd = m_nrjbPacketConstructer.constructReadAllTitles(ui->lineEditTcpServerAddr->text(), ui->comboBoxLocalHostAddr->currentText());
    m_connection->sendTcpMsg(readTitleCmd);
}

// 读取所有的信息
void NRJB103Client::slot_pushButtonReadAll_clicked()
{ 
    qDebug() << "请求数据";
    m_recvList.clear();
    // 第一步先请求标题数据
    readAllTitlesInfo();
}

void NRJB103Client::slot_responseForUserApi()
{
    if (isCanComminucate) {
        m_recvList.clear();
        // 第一步先请求标题数据
        readAllTitlesInfo();
    }
}

void NRJB103Client::slot_getBillInfo()
{
    m_tablesInfo = m_NRJBParser.getStructBillInfo();
}

void NRJB103Client::slot_ConnectError()
{
    m_errorList.append("连接超时");
    if (m_timerConnectDev.isActive()) {
        m_timerConnectDev.stop();
    }

    if ( m_timerReadDeviceRequest.isActive()) {
        m_timerReadDeviceRequest.stop();
    }
}

void NRJB103Client::slot_setCanReadBillInfo()
{
    m_timerReadDeviceRequest.stop();        //在完成标题读取后， 停掉定时检查是否可以进行读取操作，继续下一步读取各个组具体信息
//    m_canGetBillInfo = true;
    ui->textBrowserRecv->append("**** 可以读取定值信息。****");
    readAllGroupsInfo();
}
